//
//@author jltxseo
// Created by junlintianxia on 2019/5/6.
//
#include <string.h>
#include <jni.h>
#include<malloc.h>
#include <android/log.h>
#include "JniThread.h"
#include "pthread.h"
#include "JavaListener.h"

#define LOG_TAG "ndk.out.c"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

//声明一个线程
pthread_t pthread;

void *threadCallback(void *data){
    LOGI("Hello From C++ Thread");
    //执行线程完毕之后，退出线程
    pthread_exit(&pthread);
}

/*
 * Class:     com_jltx_xq_javajni_JniThread
 * Method:    createThread
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_jltx_xq_javajni_JniThread_createThread
(JNIEnv *env, jclass cls)
{
    //创建 thread 对象
    pthread_create(&pthread, NULL, threadCallback, NULL);
}

/*
 * Class:     com_jltx_xq_javajni_JniThread
 * Method:    callJavaMethodOnMainThread
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_jltx_xq_javajni_JniThread_callJavaMethodOnMainThread
(JNIEnv *env, jclass cls)
{
    //获取到class的引用，并且该类不能混淆
    jclass jcls = env->FindClass("com/jltx/xq/javajni/JniThread");
    if(jcls == 0){
        LOGI("find class error");
    }
    LOGI("find class ");

    jmethodID  jmethodId = env->GetStaticMethodID(jcls,"onSuccess","(Ljava/lang/String;)V");
    if(jmethodId==0){
        LOGI("find onSuccess error");
        return;
    }
    LOGI("find onSuccess ");

    //构造一个jString对象
    char *c_ptr_name1 = "I come from Native1";
    //构造一个jstring对象
    jstring cName1 = env->NewStringUTF(c_ptr_name1);

    //调用一个静态的java方法    void        (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...);
    env->CallStaticVoidMethod(jcls,jmethodId,cName1);

    env->DeleteLocalRef(cName1);
}

//子线程
pthread_t childThread;

//定义一个全局 java vm 实例
JavaVM *jvm;

//线程执行体
void *childCallback(void *data) {
    //3. 在子线程中得到主线程传递过来的 JavaListener 实例
    JavaListener *javaListener = (JavaListener *) data;
    //4. 通过 JavaListener 去执行对应的 onSuccess 函数。
    javaListener->onSuccess("hello from child thread");
    //5. 退出线程
    pthread_exit(&childThread);
}

/*
 * Class:     com_jltx_xq_javajni_JniThread
 * Method:    callJavaMethodOnChildThread
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_jltx_xq_javajni_JniThread_callJavaMethodOnChildThread
(JNIEnv *env, jclass cls){
    //1. 传递给子线程的对象 JavaListener ，**这里需要 instance 转化为全局的实例**
    //获得ArrayList类的无参构造函数的id
    jmethodID listConstructId = env->GetMethodID(cls, "<init>", "()V");
    //构建一个new ArrayList对象
    jobject jobj = env->NewObject(cls, listConstructId);

    JavaListener *javaListener = new JavaListener(jvm, env, env->NewGlobalRef(jobj));
    //2. 创建子线程，将 javaListener 传递给线程执行体 childCallback
    pthread_create(&childThread, NULL, childCallback, javaListener);
}


JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    JNIEnv *env;
    //获取java虚拟机，在jni的c线程中不允许使用共用的env环境变量 但JavaVM在整个jvm中是共用的 可通过保存JavaVM指针,到时候再通过JavaVM指针取出JNIEnv *env
    jvm = vm;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }
    return JNI_VERSION_1_6;
}

